From 9dc205189529fde0a979864341cf538e804a4c9e Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Thu, 7 Apr 2005 13:45:21 +0000 Subject: [PATCH] - uses ocaml-md5sums (code really lighter now) - try to guess objects related to ocaml bytecode binaries (still to be tested) - wrote (first draft of) pod documentation --- dh_ocaml | 274 ++++++++++++++++++------------------------------------- 1 file changed, 90 insertions(+), 184 deletions(-) diff --git a/dh_ocaml b/dh_ocaml index a813f3a6..390b1cc1 100755 --- a/dh_ocaml +++ b/dh_ocaml @@ -6,7 +6,7 @@ # Copyright (C) 2005, Stefano Zacchiroli # # Created: Fri, 01 Apr 2005 19:50:48 +0200 zack -# Last-Modified: Mon, 04 Apr 2005 20:52:23 +0200 zack +# Last-Modified: Thu, 07 Apr 2005 09:40:15 +0200 zack # # This is free software, you can redistribute it and/or modify it under the # terms of the GNU General Public License version 2 as published by the Free @@ -22,17 +22,18 @@ # Place, Suite 330, Boston, MA 02111-1307 USA # -# TODO ask Joey Hess about how much dh_ocaml follows debhelper guidelines # TODO check how dh_ocaml work when multiple binary packages are being built # TODO for libraries: add proper dependencies on ocaml (and findlib?) # TODO for binaries: check if package is shipping any bytecode binaries (head -1 # should be enough) and add proper dependencies on ocaml # TODO complete POD documentation -# TODO add comment headers for uncommented subs +# TODO check if dh_ocaml md5sums calculation works with -pack -ed units (e.g. +# Foo.Bar) =head1 NAME -dh_ocaml - compute OCaml md5sums and calculate OCaml dependencies +dh_ocaml - calculates ocaml dependencies and adds postinst and prerm ocaml +scripts =cut @@ -40,211 +41,116 @@ use strict; use Debian::Debhelper::Dh_Lib; init(); -# dh_perl documentation follows, cut and pasted here since I don't know POD -# syntax -# -- Zack -# -# =head1 SYNOPSIS -# -# B [S>] [B<-d>] [S>] -# -# =head1 DESCRIPTION -# -# dh_perl is a debhelper program that is responsible for generating -# the ${perl:Depends} substitutions and adding them to substvars files. -# -# The program will look at perl scripts and modules in your package, -# and will use this information to generate a dependency on perl or -# perlapi. The dependency will be substituted into your package's control -# file wherever you place the token "${perl:Depends}". -# -# =head1 OPTIONS -# -# =over 4 -# -# =item B<-d> -# -# In some specific cases you may want to depend on perl-base rather than the -# full perl package. If so, you can pass the -d option to make dh_perl generate -# a dependency on the correct base package. This is only necessary for some -# packages that are included in the base system. -# -# Note that this flag may cause no dependency on perl-base to be generated at -# all. perl-base is Essential, so its dependency can be left out, unless a -# versioned dependency is needed. -# -# =item B<-V> -# -# By default, scripts and architecture independent modules don't depend -# on any specific version of perl. The -V option causes the current -# version of the perl (or perl-base with -d) package to be specified. -# -# =item I -# -# If your package installs perl modules in non-standard -# directories, you can make dh_perl check those directories by passing their -# names on the command line. It will only check the vendorlib and vendorarch -# directories by default. -# -# =back -# -# =head1 CONFORMS TO -# -# Debian policy, version 3.0.1 -# -# Perl policy, version 1.18 -# -# =cut - my $ocamlc = "/usr/bin/ocamlc"; -my $ocamlobjinfo = "/usr/bin/ocamlobjinfo"; -foreach my $bin ($ocamlc, $ocamlobjinfo) { +# my $ocaml_md5sums = "/usr/bin/ocaml-md5sums"; +my $ocaml_md5sums = "/home/zack/dati/source/ocaml/dh_ocaml/ocaml-md5sums"; +my @binaries = ($ocamlc, $ocaml_md5sums); +foreach my $bin (@binaries) { error "$bin does not exists or is not executable" unless -x $bin; } +chomp (my $ocaml_lib_dir = `$ocamlc -where`); -my $ocaml_version = `$ocamlc -version`; -my $ocaml_lib_dir = `$ocamlc -where`; -chomp ($ocaml_version, $ocaml_lib_dir); my $md5sums_dir = "/var/lib/ocaml/md5sums"; my $md5sums_ext = ".md5sums"; -my $md5sums_registry_path = "$md5sums_dir/MD5SUMS"; -my $dep_substvar = "ocaml:Depends"; +my $ocaml_magic_line = "#!/usr/bin/ocamlrun"; + +=head1 SYNOPSIS + +B [S>] + +=head1 DESCRIPTION + +dh_ocaml is a debhelper program that is responsible for generating +the ${ocaml:Depends} substitutions and adding them to substvars files. It will +also add a postinst and prerm script if required. + +The program will look at ocaml objects (files matching *.cm[ao]) shipped by your +package. From them, dh_ocaml uses ocamlobjinfo for collecting information about +ocaml modules (or units, in ocamlobjinfo terminology) defined and used by your +package. Collected information will be used both for extracting dependencies +information from the local ocaml md5sums registry (stored in +/var/lib/ocaml/md5sums/MD5SUMS) and for creating libfoo-ocaml-dev.md5sums entry +for the registry. + +Dependencies information will be used for filling the ${ocaml:Depends} +subtitution while .md5sums entry will be installed in /var/lib/ocaml/md5sums/. +If such an entry gets installed, postinst and prerm script will also be created +in order to update the registry at package install/removal time. + +=head1 CONFORMS TO + +Debian policy, version 3.6.1.1 -# given as input a directory, returns a list of all ocaml objects installed (at -# any depth) in that directory -sub find_objects($) { +OCaml packaging policy, version 0.6 + +=cut + +# find ocaml bytecode executables contained in a given directory +sub find_ocaml_bc_binaries($) { my ($dir) = @_; - my $cmd = "find $dir$ocaml_lib_dir -type f -name '*.cma'"; - verbose_print $cmd; - my $out = `$cmd` or error "can't execute \"$cmd\" for pipe-reading"; - my @objects = split /\n/, $out; - return @objects; + my @binaries = split /\n/, `find $dir -type f -perm -0100`; + my @bc_binaries; + foreach my $bin (@binaries) { + my $line = `/usr/bin/head -1 $bin` or next; + chomp $line; + push @bc_binaries, $line if $line eq $ocaml_magic_line; + } + return @bc_binaries; } -# globals -my %defined_md5sums; # (unit name -> md5sum) mappings for units _defined_ by - # package's objects -my %imported_md5sums; # same mappings for units _imported_ by package's objects -my %md5sums_registry; # parsed version of local md5sums registry -my $registry_parsed = 0; # flag used for lazy registry parsing - -# given as input a list of ocaml object filenames, fills -# %{defin,import}ed_md5sums. Use ocamlobjinfo to retrieve md5sum information -sub compute_md5sums(@) { - my @objects = @_; - my %md5sums; - foreach my $object (@objects) { - my $cmd = "$ocamlobjinfo $object"; - verbose_print "\"$cmd\""; - open OBJINFO, "$cmd |" or error "can't execute \"$cmd\" for pipe-reading"; - my $unit_name = ""; - while (my $line = ) { +# read ocaml dependencies information from file and fill ocaml:Depends substvar +sub fill_ocaml_depends($$) { + my ($package, $fname) = @_; + delsubstvar($package, "ocaml:Depends"); + if (-f $fname) { + open DEPS, "< $fname" or die "Can't open $fname"; + while (my $line = ) { chomp $line; - if ($line =~ /^\s*Unit\s+name\s*:\s*(\w+)\s*$/) { - $unit_name = $1; -# verbose_print "Unit $unit_name"; - } elsif ($line =~ /^\s*([0-9A-Fa-f]{32})\s+(\w+)\s*$/) { - if ($2 eq $unit_name) { - $defined_md5sums{$2} = $1; -# verbose_print "Defined $1 $2"; - } else { - $imported_md5sums{$2} = $1; -# verbose_print "Imported $1 $2"; - } - } + my ($dep_package, $dep_version) = split /\s+/, $line; + next unless $dep_package and $dep_version; + addsubstvar($package, "ocaml:Depends", $dep_package, ">= $dep_version"); } - close OBJINFO; + close DEPS; } } -# create /var/lib/ocaml/md5sums/ entry and create post{inst,rm} scripts for -# updating md5sums registry on users' machines -sub add_md5sums_registry_entry($) { - my ($package) = @_; +# main +foreach my $package (@{$dh{DOPACKAGES}}) { my $tmpdir = tmpdir($package); - my $md5sums_fname = "$tmpdir$md5sums_dir/$package$md5sums_ext"; - doit("mkdir -p " . dirname($md5sums_fname)); - open MD5SUMS, "> $md5sums_fname"; - foreach my $unit_name (sort (keys %defined_md5sums)) { - print MD5SUMS "$defined_md5sums{$unit_name} $unit_name\n"; - } - close MD5SUMS; - if (! $dh{NOSCRIPTS}) { + isnative($package); # sets $dh{VERSION} + my $flags = "--package $package --version $dh{VERSION}"; + my $objinfo = "debian/$package.ocamlobjinfo~"; + my $objlist = "debian/$package.ocamlobjects~"; + my $ocamldeps = "debian/$package.ocamldeps~"; + if ($package =~ /^lib.*-ocaml-dev$/) { # ocaml library package + # create md5sum registry entry and post{inst,rm} scripts + complex_doit("/usr/bin/find $tmpdir$ocaml_lib_dir -type f -name '*.cm[ao]' " + . "> $objlist"); + complex_doit("mkdir -p $tmpdir$md5sums_dir"); + complex_doit("$ocaml_md5sums $flags --dump-info $objinfo compute < $objlist" + . " | /usr/bin/sort -k 2" # optional pass, just for "pretty" printing + . " > $tmpdir$md5sums_dir/$package$md5sums_ext"); my $sed = "s/#PACKAGE#/$package/; s/#VERSION#/$dh{VERSION}/"; autoscript($package, "postinst", "postinst-ocaml", $sed); autoscript($package, "postrm", "postrm-ocaml", $sed); - } -} - -# lazy parsing of md5sum registry /var/lib/ocaml/md5sums/MD5SUMS -sub load_md5sum_registry() { - if (! $registry_parsed) { - open REGISTRY, $md5sums_registry_path; - my $lineno = 0; - while (my $line = ) { - $lineno++; - chomp $line; - next if $line =~ /(^#)|(^\s*$)/; # skip blank lines and comments - if ($line =~ /^([0-9A-Fa-f]{32})(\s+\S+){3}$/) { - my ($md5sum, $package, $version, $unit_name) = split /\s+/, $line; - # mappings like: - # "9b93712a344b3b9849a73ce19d8c72ce Foo_bar"->"libfoo-ocaml-dev 0.2.3-5" - my $key = "$md5sum $unit_name"; - if (exists($md5sums_registry{$key})) { - warning("multiple entries for $key in md5sums registry, " - . "ocaml dependencies may be wrong"); - } - $md5sums_registry{$key} = "$package $version"; - } else { - warning - "can't parse md5sums registry line ($md5sums_registry_path:$lineno)"; - next; - } + # compute deps for the library + complex_doit("$ocaml_md5sums $flags --load-info $objinfo dep < $objlist" + . " > $ocamldeps"); + } else { # ocaml binary package + my @binaries = find_ocaml_bc_binaries($tmpdir); + complex_doit "> $ocamldeps"; + foreach my $bin (@binaries) { # try to find .cmo of bc binaries + my $guess = basename($bin) . ".cm[ao]"; + complex_doit("/usr/bin/find . -type f -name '$guess' >> $ocamldeps"); } - close REGISTRY; - $registry_parsed = 1; - } -} - -sub lookup_dep($$) { - my ($md5sum, $unit_name) = @_; - load_md5sum_registry(); - my $dep = $md5sums_registry{"$md5sum $unit_name"}; - if ($dep) { - my ($deppackage, $version) = split /\s+/, $dep; - return($deppackage, ">= $version"); - } else { - return(0, 0); - } -} - -# compute dependencies of package using md5sum registry installed on the machine -# which is building the package -sub fill_substvars($) { - my ($package) = @_; - my $tmpdir = tmpdir($package); - delsubstvar($package, $dep_substvar); # idempotency - foreach my $unit_name (sort (keys %imported_md5sums)) { - next if exists $defined_md5sums{$unit_name}; - my ($deppackage, $verinfo) = - lookup_dep($imported_md5sums{$unit_name}, $unit_name); - addsubstvar($package, $dep_substvar, $deppackage, $verinfo) if $deppackage; + complex_doit("$ocaml_md5sums $flags dep < $objlist > $ocamldeps"); } -} - -foreach my $package (@{$dh{DOPACKAGES}}) { - next unless $package =~ /^lib.*-ocaml-dev$/; - isnative($package); # sets $dh{VERSION} - my $tmpdir = tmpdir($package); - my @objects = find_objects($tmpdir); - compute_md5sums(@objects); # fills %{defined,imported}_md5sums globals - add_md5sums_registry_entry($package); - fill_substvars($package); + fill_ocaml_depends($package, $ocamldeps); } =head1 SEE ALSO -L +L, L This program is a part of debhelper. -- 2.30.2